package com.engine.hikvision.service.impl;

import cn.hutool.core.thread.ThreadUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.engine.core.impl.Service;
import com.engine.hikvision.service.HikVisionService;
import com.engine.hikvision.utils.HikVisionApiUtil;
import com.engine.kq.biz.KQFormatBiz;
import com.engine.kq.wfset.util.SplitActionUtil;
import com.huawei.shade.org.joda.time.DateTime;
import com.huawei.shade.org.joda.time.format.DateTimeFormat;
import com.huawei.shade.org.joda.time.format.DateTimeFormatter;
import com.mzlion.core.lang.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.hsqldb.lib.StringUtil;
import weaver.conn.RecordSet;
import weaver.formmode.setup.ModeRightInfo;
import weaver.general.BaseBean;
import weaver.general.Util;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ExecutorService;

public class HikVisionServiceImpl extends Service implements HikVisionService {

    BaseBean baseBean = new BaseBean();

    @Override
    public Map<String, Object> syncPersonDoorData(Map<String, Object> paramMap) {
        baseBean.writeLog("syncPersonDoorData start:" + paramMap);
        Map<String, Object> apidatas = new HashMap<>();
        String startdate = Util.null2String(paramMap.get("startdate"));
        String enddate = Util.null2String(paramMap.get("enddate"));
        String ygxm = Util.null2String(paramMap.get("ygxm"));
        if (StringUtils.isEmpty(ygxm)) {
            apidatas.put("sign", "-1");
            apidatas.put("message", "请输入同步的人员");
            return apidatas;
        }
        RecordSet rs = new RecordSet();
        String sql = "SELECT lastname from hrmresource where id in (" + ygxm + ")";
        rs.execute(sql);
        baseBean.writeLog("syncPersonDoorData get name sql:" + sql);
        List<String> ygxmList = new ArrayList<>();
        while (rs.next()) {
            ygxmList.add(rs.getString("lastname"));
        }
        if (org.springframework.util.CollectionUtils.isEmpty(ygxmList)) {
            apidatas.put("sign", "-1");
            apidatas.put("message", "员工姓名获取失败，请联系管理员");
            return apidatas;
        }

        // 同步食堂打卡数据
        try {
            int corePoolSize = 2;
            int maxPoolSize = 5;
            ExecutorService executorService = ThreadUtil.newExecutor(corePoolSize, maxPoolSize);
            executorService.submit(() -> {
                syncCanteenDoorData(startdate, enddate, ygxmList);
            });
        } catch (Exception e) {
            baseBean.writeLog("first syncCanteenDoorData error:" + e);
        }

        String startDateBefore = HikVisionApiUtil.beforeDay(startdate, 1);
        String endDateAfter = HikVisionApiUtil.beforeDay(enddate, 1);

        rs.execute("select * from HrmScheduleSign WHERE userId in (" + ygxm + ") and belongdate between '" + startDateBefore + "' and '" + endDateAfter + "'");
        List<List> allParams = new ArrayList<>();
        while (rs.next()) {
            List param = new ArrayList<String>();
            param.add(rs.getInt("userId"));
            param.add(rs.getString("userType"));
            param.add(rs.getString("signType"));
            param.add(rs.getString("signDate"));
            param.add(rs.getString("signTime"));
            param.add(rs.getString("isInCom"));
            param.add(rs.getString("signFrom"));
            param.add(rs.getString("timeZone"));
            param.add(rs.getString("belongdate"));
            param.add(rs.getString("addr"));
            allParams.add(param);
        }

        String workCodePrefixStr = baseBean.getPropValue("hikvisiondoorindexcode", "WORK_CODE_PREFIX");

        try {
            Map<String, Integer> certNoAndIdMap = getCertNoAndIdMap();
            Set<String> ryrqSet = new HashSet<>();
            for (String name : ygxmList) {
                Map<String, Object> map = new HashMap<String, Object>();
                String startTime = startdate + "T00:00:01+08:00";
                String endTime = enddate + "T23:59:59+08:00";
                map.put("startTime", startTime);
                map.put("endTime", endTime);
                map.put("pageSize", "1000");
                map.put("personName", name);

                String doorIndexCodeStr = baseBean.getPropValue("hikvisiondoorindexcode", "ATTENDANCE_DOOR_INDEX_CODES");
                String[] doorIndexCodes = null;
                if (StringUtils.isNotEmpty(doorIndexCodeStr)) {
                    doorIndexCodes = doorIndexCodeStr.split(",");
                    for (String s : doorIndexCodes) {
                        int pageNo = 1;
                        boolean isGoing = true;
                        List<String> tempIndexCodes = new ArrayList<>();
                        tempIndexCodes.add(s);
                        map.put("doorIndexCodes", tempIndexCodes.toArray());
                        while (isGoing) {
                            map.put("pageNo", String.valueOf(pageNo));
                            baseBean.writeLog("begin to sync door data:" + map);
                            String result = HikVisionApiUtil.callPostApiList("/api/acs/v2/door/events", map);
                            JSONObject obj = JSON.parseObject(result);
                            JSONObject dataObj = obj.getJSONObject("data");
                            JSONArray jsonList = dataObj.getJSONArray("list");
                            if (dataObj.getInteger("totalPage") > pageNo) {
                                pageNo += 1;
                            } else {
                                isGoing = false;
                            }
                            baseBean.writeLog("jsonList:", jsonList);
                            List<List> insertParams = new ArrayList<>();
                            for (int i = 0; i < jsonList.size(); i++) {
                                List insertParam = new ArrayList<>();
                                JSONObject jsonObject = jsonList.getJSONObject(i);
                                String certNo = jsonObject.getString("jobNo");
                                if (StringUtil.isEmpty(certNo)) {
                                    continue;
                                }
                                if (org.apache.commons.lang3.StringUtils.isNotEmpty(workCodePrefixStr) && !certNo.startsWith(workCodePrefixStr)) {
                                    continue;
                                }
                                Integer userId = certNoAndIdMap.get(certNo);
                                String userType = "1";
                                String signType = jsonObject.getInteger("inAndOutType") == 1 ? "1" : "2";
                                String eventTime = jsonObject.getString("eventTime");
                                String[] arr = getDateStrFromIso8601(eventTime).split("\\s+");
                                String signDate = arr[0];
                                String signTime = arr[1];
                                String isInCom = "1";  // 1:有效; 0:无效
                                String signFrom = jsonObject.getString("doorName");
                                String timeZone = "GMT+8";
                                String belongdate = signDate;
                                insertParam.add(userId);
                                insertParam.add(userType);
                                insertParam.add(signType);
                                insertParam.add(signDate);
                                insertParam.add(signTime);
                                insertParam.add(isInCom);
                                insertParam.add("海康考勤机");
                                insertParam.add(timeZone);
                                insertParam.add(belongdate);
                                insertParam.add(signFrom);
                                insertParams.add(insertParam);

                                String key = userId + "=" + belongdate;
                                ryrqSet.add(key);
                            }
                            List<List> insertParamsNew = new ArrayList<>();
                            for (int i = 0; i < insertParams.size(); i++) {
                                if (!allParams.contains(insertParams.get(i))) {
                                    insertParamsNew.add(insertParams.get(i));
                                }
                            }
                            if (CollectionUtils.isNotEmpty(insertParamsNew)) {
                                String insertSql = "INSERT INTO HrmScheduleSign(userId, userType, signType, signDate, signTime, isInCom, " +
                                        "signFrom, timeZone, belongdate, addr) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
                                rs.executeBatchSql(insertSql, insertParamsNew);
                            }
                        }
                    }
                }
            }

            if (!org.springframework.util.CollectionUtils.isEmpty(ryrqSet)) {
                for (String key : ryrqSet) {
                    if (StringUtils.isEmpty(key)) {
                        continue;
                    }
                    String[] split = key.split("=");
                    String uid = split[0];
                    String dateT = split[1];
                    if (StringUtils.isEmpty(uid) || StringUtils.isEmpty(dateT)) {
                        continue;
                    }
                    new KQFormatBiz().formatDate(uid, dateT);
                    //处理加班生成
                    SplitActionUtil.pushOverTimeTasksAll(dateT, dateT, uid);
                }
            }

            baseBean.writeLog("end to sync door data");
            apidatas.put("sign", "1");
            apidatas.put("message", "同步成功！");
        } catch (Exception e) {

        }
        return apidatas;
    }

    public void syncCanteenDoorData(String startdate, String enddate, List<String> ygxmList) {
        RecordSet rs = new RecordSet();
        try {
            SimpleDateFormat sdfDate = new SimpleDateFormat("yyyy-MM-dd");
            SimpleDateFormat sdfTime = new SimpleDateFormat("HH:mm:ss");
            String startDateBefore = HikVisionApiUtil.beforeDay(startdate, 1);
            String endDateAfter = HikVisionApiUtil.beforeDay(enddate, 1);

            String sql = "select * from uf_stdkjcsjb where dkrq between '" + startDateBefore + "' and '" + endDateAfter + "'";
            baseBean.writeLog("SyncCanteenDoorData sql is:" + sql);
            rs.execute(sql);
            Set<String> keySet = new HashSet<>();
            while (rs.next()) {
                String gh = rs.getString("gh");
                String dkrq = rs.getString("dkrq");
                String dksj = rs.getString("dksj");
                String kjxx = rs.getString("kjxx");
                String key = gh + "-" + dkrq + "-" + dksj + "-" + kjxx;
                keySet.add(key);
            }

            Map<String, String> certNoAndIdMap = new HashMap<>();
            Map<String, String> idAndDeptMap = new HashMap<>();
            Map<String, String> idAndComMap = new HashMap<>();
            rs.execute("select id, workcode, departmentid, SUBCOMPANYID1 from hrmresource");
            while (rs.next()) {
                String id = rs.getString("id");
                String workcode = rs.getString("workcode");
                String departmentid = rs.getString("departmentid");
                String fb = rs.getString("SUBCOMPANYID1");
                certNoAndIdMap.put(workcode, id);
                idAndDeptMap.put(id, departmentid);
                idAndComMap.put(id, fb);
            }
            String workCodePrefixStr = baseBean.getPropValue("hikvisiondoorindexcode", "WORK_CODE_PREFIX");
            String doorIndexCodeStr = baseBean.getPropValue("hikvisiondoorindexcode", "CANTEEN_DOOR_INDEX_CODES");

            for (String name : ygxmList) {
                Map<String, Object> map = new HashMap<String, Object>();
                String startTime = startdate + "T00:00:01+08:00";
                String endTime = enddate + "T23:59:59+08:00";
                map.put("startTime", startTime);
                map.put("endTime", endTime);
                map.put("pageSize", "1000");
                map.put("personName", name);

                String[] doorIndexCodes = null;
                if (StringUtils.isNotEmpty(doorIndexCodeStr)) {
                    doorIndexCodes = doorIndexCodeStr.split(",");
                    for (String s : doorIndexCodes) {
                        int pageNo = 1;
                        boolean isGoing = true;
                        List<String> tempIndexCodes = new ArrayList<>();
                        tempIndexCodes.add(s);
                        map.put("doorIndexCodes", tempIndexCodes.toArray());
                        while (isGoing) {
                            map.put("pageNo", String.valueOf(pageNo));
                            baseBean.writeLog("begin to sync canteen door data:" + map);
                            String result = HikVisionApiUtil.callPostApiList("/api/acs/v2/door/events", map);
                            JSONObject obj = JSON.parseObject(result);
                            JSONObject dataObj = obj.getJSONObject("data");
                            JSONArray jsonList = dataObj.getJSONArray("list");
                            if (dataObj.getInteger("totalPage") > pageNo) {
                                pageNo += 1;
                            } else {
                                isGoing = false;
                            }
                            List<List> insertParams = new ArrayList<>();
                            for (int i = 0; i < jsonList.size(); i++) {
                                JSONObject jsonObject = jsonList.getJSONObject(i);
                                String certNo = jsonObject.getString("jobNo");
                                if (StringUtil.isEmpty(certNo)) {
                                    continue;
                                }
                                if (org.apache.commons.lang3.StringUtils.isNotEmpty(workCodePrefixStr) && !certNo.startsWith(workCodePrefixStr)) {
                                    continue;
                                }
                                String userId = certNoAndIdMap.get(certNo);
                                String eventTime = jsonObject.getString("eventTime");
                                String[] arr = getDateStrFromIso8601(eventTime).split("\\s+");
                                String signDate = arr[0];
                                String signTime = arr[1];
                                String signFrom = jsonObject.getString("doorName");

                                String keyTemp = certNo + "-" + signDate + "-" + signTime + "-" + signFrom;
                                if ((!org.springframework.util.CollectionUtils.isEmpty(keySet)) && keySet.contains(keyTemp)) {
                                    continue;
                                }

                                String bm = idAndDeptMap.get(userId);
                                String fb = idAndComMap.get(userId);
                                String nowDate = sdfDate.format(new Date());
                                String nowTime = sdfTime.format(new Date());

                                List insertParam = new ArrayList<>();
                                insertParam.add(userId);
                                insertParam.add(certNo);
                                insertParam.add(signDate);
                                insertParam.add(signTime);
                                insertParam.add(signFrom);
                                insertParam.add("16");
                                insertParam.add(UUID.randomUUID().toString());
                                insertParam.add("1");
                                insertParam.add("0");
                                insertParam.add(nowDate);
                                insertParam.add(nowTime);
                                insertParam.add("0");
                                insertParam.add(bm);
                                insertParam.add(fb);
                                insertParams.add(insertParam);
                            }
                            if (CollectionUtils.isNotEmpty(insertParams)) {
                                String insertSql = "INSERT INTO uf_stdkjcsjb(xm, gh, dkrq, dksj, kjxx, formmodeid, MODEUUID, " +
                                        "modedatacreater,modedatacreatertype, modedatacreatedate, modedatacreatetime, ytj, bm, fb) VALUES " +
                                        "(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
                                rs.executeBatchSql(insertSql, insertParams);
                            }
                        }
                    }
                }
            }

            // 统计食堂打卡信息
            handleCanteenCnt();
            baseBean.writeLog("end to sync canteen door data.");
        } catch (Exception e) {
            baseBean.writeLog("syncCanteenDoorData error:" + e);
        }
    }

    public String getDateStrFromIso8601(String dateStr){
        DateTimeFormatter dtf1 = DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ssZZ");
        DateTime dt= dtf1.parseDateTime(dateStr);
        DateTimeFormatter dtf2= DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss");
        return dt.toString(dtf2);
    }

    public Map<String, Integer> getCertNoAndIdMap() {
        Map<String, Integer> certNoAndIdMap = new HashMap<>();
        RecordSet rs = new RecordSet();
        rs.execute("select id, workcode from hrmresource");
        while (rs.next()) {
            certNoAndIdMap.put(rs.getString("workcode"), rs.getInt("id"));
        }
        return certNoAndIdMap;
    }

    public void handleCanteenCnt() {
        RecordSet rsCt = new RecordSet();
        BaseBean bs1 = new BaseBean();
        bs1.writeLog("handleCanteenCnt start.");
        try {
            // 获取三餐对应时间
            String zcStart = null;
            String zcEnd = null;
            String zcSfkt = null;
            String wcStart = null;
            String wcEnd = null;
            String wcSfkt = null;
            String ywcStart = null;
            String ywcEnd = null;
            String ywcSfkt = null;
            String yxStart = null;
            String yxEnd = null;
            String yxSfkt = null;
            rsCt.execute("SELECT * FROM uf_scsjglb");
            while (rsCt.next()) {
                if (org.apache.commons.lang3.StringUtils.equals("0", rsCt.getString("lb"))) {
                    zcStart = rsCt.getString("kssj");
                    zcEnd = rsCt.getString("jssj");
                    zcSfkt = rsCt.getString("sfkt");
                }
                if (org.apache.commons.lang3.StringUtils.equals("1", rsCt.getString("lb"))) {
                    wcStart = rsCt.getString("kssj");
                    wcEnd = rsCt.getString("jssj");
                    wcSfkt = rsCt.getString("sfkt");
                }
                if (org.apache.commons.lang3.StringUtils.equals("2", rsCt.getString("lb"))) {
                    ywcStart = rsCt.getString("kssj");
                    ywcEnd = rsCt.getString("jssj");
                    ywcSfkt = rsCt.getString("sfkt");
                }
                if (org.apache.commons.lang3.StringUtils.equals("3", rsCt.getString("lb"))) {
                    yxStart = rsCt.getString("kssj");
                    yxEnd = rsCt.getString("jssj");
                    yxSfkt = rsCt.getString("sfkt");
                }
            }

            List<List> insertParams = new ArrayList<>();
            SimpleDateFormat sdfDate = new SimpleDateFormat("yyyy-MM-dd");
            SimpleDateFormat sdfTime = new SimpleDateFormat("HH:mm:ss");
            List<String> idSet = new ArrayList<>();
            // 获取所有未统计的数据
            rsCt.execute("SELECT * FROM uf_stdkjcsjb WHERE ytj is null or ytj = '' or ytj = 0");
            while (rsCt.next()) {
                String id = rsCt.getString("id");
                String gh = rsCt.getString("gh");
                String xm = rsCt.getString("xm");
                String dkrq = rsCt.getString("dkrq");
                String dksj = rsCt.getString("dksj");
                String kjxx = rsCt.getString("kjxx");

                String zccs = "0";
                if (org.apache.commons.lang.StringUtils.isNotEmpty(zcStart) && org.apache.commons.lang.StringUtils.isNotEmpty(zcEnd)) {
                    String zcStartT = dkrq + " " + zcStart;
                    String zcEndT = dkrq + " " + zcEnd;
                    if (org.apache.commons.lang.StringUtils.equals("1", zcSfkt)) {
                        zcEndT = HikVisionApiUtil.AfterDay(dkrq, 1) + " " + zcEnd;
                    }
                    if (HikVisionApiUtil.getTime(dkrq + " " + dksj).compareTo(HikVisionApiUtil.getTime(zcEndT)) <= 0
                            && HikVisionApiUtil.getTime(dkrq + " " + dksj).compareTo(HikVisionApiUtil.getTime(zcStartT)) >= 0) {
                        zccs = "1";
                    }
                }

                String wccss = "0";
                if (org.apache.commons.lang.StringUtils.isNotEmpty(wcStart) && org.apache.commons.lang.StringUtils.isNotEmpty(wcEnd)) {
                    String wcStartT = dkrq + " " + wcStart;
                    String wcEndT = dkrq + " " + wcEnd;
                    if (org.apache.commons.lang.StringUtils.equals("1", wcSfkt)) {
                        wcEndT = HikVisionApiUtil.AfterDay(dkrq, 1) + " " + wcEndT;
                    }
                    if (HikVisionApiUtil.getTime(dkrq + " " + dksj).compareTo(HikVisionApiUtil.getTime(wcEndT)) <= 0
                            && HikVisionApiUtil.getTime(dkrq + " " + dksj).compareTo(HikVisionApiUtil.getTime(wcStartT)) >= 0) {
                        wccss = "1";
                    }
                }

                String wccs = "0";
                if (org.apache.commons.lang.StringUtils.isNotEmpty(ywcStart) && org.apache.commons.lang.StringUtils.isNotEmpty(ywcEnd)) {
                    String ywcStartT = dkrq + " " + ywcStart;
                    String ywcEndT = dkrq + " " + ywcEnd;
                    if (org.apache.commons.lang.StringUtils.equals("1", ywcSfkt)) {
                        ywcEndT = HikVisionApiUtil.AfterDay(dkrq, 1) + " " + ywcEnd;
                    }
                    if (HikVisionApiUtil.getTime(dkrq + " " + dksj).compareTo(HikVisionApiUtil.getTime(ywcEndT)) <= 0
                            && HikVisionApiUtil.getTime(dkrq + " " + dksj).compareTo(HikVisionApiUtil.getTime(ywcStartT)) >= 0) {
                        wccs = "1";
                    }
                }

                String xycs = "0";
                if (org.apache.commons.lang.StringUtils.isNotEmpty(yxStart) && org.apache.commons.lang.StringUtils.isNotEmpty(yxEnd)) {
                    String yxStartT = dkrq + " " + yxStart;
                    String yxEndT = dkrq + " " + yxEnd;
                    if (org.apache.commons.lang.StringUtils.equals("1", yxSfkt)) {
                        yxEndT = HikVisionApiUtil.AfterDay(dkrq, 1) + " " + yxEnd;
                    }
                    if (HikVisionApiUtil.getTime(dkrq + " " + dksj).compareTo(HikVisionApiUtil.getTime(yxEndT)) <= 0
                            && HikVisionApiUtil.getTime(dkrq + " " + dksj).compareTo(HikVisionApiUtil.getTime(yxStartT)) >= 0) {
                        xycs = "1";
                    }
                }

                String nowDate = sdfDate.format(new Date());
                String nowTime = sdfTime.format(new Date());

                List insertParam = new ArrayList<>();
                insertParam.add(gh);
                insertParam.add(dkrq);
                insertParam.add(xm);
                insertParam.add(dksj);
                insertParam.add(kjxx);
                insertParam.add(zccs);
                insertParam.add(wccss);
                insertParam.add(wccs);
                insertParam.add(xycs);
                insertParam.add("13");
                insertParam.add(UUID.randomUUID().toString());
                insertParam.add(1);
                insertParam.add(0);
                insertParam.add(nowDate);
                insertParam.add(nowTime);
                insertParams.add(insertParam);
                idSet.add(id);
            }

            // 将涉及的数据更新为已同步
            if (CollectionUtils.isNotEmpty(idSet)) {
                if (idSet.size() <= 1000) {
                    String ids = String.join(",", idSet);
                    rsCt.execute("UPDATE uf_stdkjcsjb SET ytj = 1 WHERE id in (" + ids + ")");
                } else {
                    int batchSize = 1000; // 每个小集合的大小
                    int size = idSet.size(); // 原始集合的大小
                    int numberOfBatches = (int) Math.ceil((double) size / batchSize); // 划分的小集合数量
                    List<List<String>> dividedLists = new ArrayList<>(); // 存储划分后的小集合

                    for (int i = 0; i < numberOfBatches; i++) {
                        int fromIndex = i * batchSize;
                        int toIndex = Math.min((i + 1) * batchSize, size);
                        List<String> batch = idSet.subList(fromIndex, toIndex);
                        dividedLists.add(batch);
                    }

                    for (List<String> batch : dividedLists) {
                        String ids = String.join(",", batch);
                        rsCt.execute("UPDATE uf_stdkjcsjb SET ytj = 1 WHERE id in (" + ids + ")");
                    }
                }
            }

            if (CollectionUtils.isNotEmpty(insertParams)) {
                String insertSql = "INSERT INTO uf_stdkxx(bh, dkrq, xm, dksj, kjxx, zccs, wccss, wccs, xycs, formmodeid, MODEUUID, " +
                        "modedatacreater,modedatacreatertype, modedatacreatedate, modedatacreatetime) VALUES " +
                        "(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
                rsCt.executeBatchSql(insertSql, insertParams);
            }

            // 权限重构
            ModeRightInfo modeRightInfo = new ModeRightInfo();
            modeRightInfo.setNewRight(true);
            modeRightInfo.editModeDataShare(1, 13, 19);
        } catch (Exception e) {
            bs1.writeLog("handleCanteenCnt error:" + e);
        }
        bs1.writeLog("handleCanteenCnt end.");
    }
}
